from captcha.models import CaptchaStore
from django.contrib.auth import get_user_model
from django_redis import get_redis_connection
from rest_framework import serializers, status
from datetime import datetime
from . import constants

User = get_user_model()


class CheckImageCodeSerializer(serializers.Serializer):
    """
    图片验证码校验序列化
    """
    image_code_id = serializers.CharField(required=True)
    text = serializers.CharField(max_length=4, min_length=4)
    mobile = serializers.CharField(max_length=11, min_length=11, allow_null=True)
    account = serializers.CharField(min_length=4, max_length=11, allow_null=True)

    def validate(self, attrs):
        """
        验证图片验证码是否正确，查询数据库获取真实验证码
        :param attrs:
        :return:
        """
        image_code_id = attrs['image_code_id']
        text = attrs['text']
        try:
            real_image_code = CaptchaStore.objects.get(hashkey=image_code_id)
            if real_image_code is None:
                raise serializers.ValidationError("无效的图片验证码")
            else:
                real_image_code.delete()
                if datetime.now() > real_image_code.expiration:
                    raise serializers.ValidationError("图片验证码已经过期")
                elif text.lower() != real_image_code.response:
                    raise serializers.ValidationError("验证码输入错误")
                else:
                    # redis中发送短信验证码的标志，send_flag<mobile> :1，由redisl来维护60s的有效期
                    redis_conn = get_redis_connection('verify_codes')
                    # 从rest url中的参数获取字段
                    mobile = attrs['mobile']
                    if mobile is not None:
                        send_flag = redis_conn.get(constants.REGISTER_SMS_CODE_FLAG + ":" + mobile)
                        if send_flag:
                            raise serializers.ValidationError("发送短信次数过于频繁")

                    return attrs
        except:
            raise serializers.ValidationError("图片验证码已经过期")


class CheckSMSCodeByTokenSerializer(serializers.Serializer):
    sms_code = serializers.CharField(required=True, allow_null=False, min_length=6, max_length=6)
    access_token = serializers.CharField(required=True, allow_null=False)

    def validate(self, attrs):
        sms_code = attrs["sms_code"]
        access_token = attrs["access_token"]

        mobile = User.check_send_sms_code_token(access_token, "mobile")

        if mobile is None:
            raise serializers.ValidationError("无效access token", status.HTTP_404_NOT_FOUND)

        redis_conn = get_redis_connection("verify_codes")
        real_sms_code = redis_conn.get(constants.REGISTER_SMS_CODE + ":" + mobile)

        if real_sms_code is None:
            raise serializers.ValidationError("验证码已经过期，请重新获取")

        else:
            if bytes.decode(real_sms_code) != sms_code:
                raise serializers.ValidationError("验证码输入不正确，请重新输入")

        return attrs
